package com.github.fashionbrot.excel;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;

public class ExcelUtil {


    private static final String LETTER = "abcdefghijklmnopqrstuvwxyz";
    private static final LinkedHashMap<String, Integer> ROW = new LinkedHashMap<>();
    private static final LinkedHashMap<Integer, String> NUMBER_COLUMN_MAP = new LinkedHashMap<>();

    static {
        int count = 0;
        for (int i = 0; i < LETTER.length(); i++) {
            char c = LETTER.charAt(i);
            ROW.put(String.valueOf(c), count);
            NUMBER_COLUMN_MAP.put(count++, String.valueOf(c));
        }

        for (int i = 0; i < LETTER.length(); i++) {
            for (int j = 0; j < LETTER.length(); j++) {
                char c1 = LETTER.charAt(i);
                char c2 = LETTER.charAt(j);
                String column = c1 + String.valueOf(c2);
                ROW.put(column, count);
                NUMBER_COLUMN_MAP.put(count++, column);
            }
        }
    }

    /**
     * 根据Excel列名获取行索引.
     *
     * @param excelColumn Excel列名
     * @return 行索引，如果找不到则返回null
     */
    public static Integer getRowColumn(String excelColumn) {
        if (excelColumn == null || excelColumn.isEmpty()) {
            return null;
        }
        // 将输入的列名转换为小写
        String column = excelColumn.toLowerCase();
        return ROW.getOrDefault(column, null);
    }

    /**
     * 根据行索引获取Excel列名.
     *
     * @param number 行索引
     * @return Excel列名，如果找不到则返回null
     */
    public static String getRowColumn(Integer number) {
        return NUMBER_COLUMN_MAP.getOrDefault(number, null);
    }

    /**
     * 从给定的工作表中按行号检索行的实用方法。
     *
     * @param sheet   要从中检索行的Excel工作表。
     * @param rowNum  要检索的行的行号。
     * @return        指定行号的行，如果工作表为null或行号超出范围，则返回null。
     */
    public static Row getRow(Sheet sheet, int rowNum) {
        if (sheet != null) {
            return sheet.getRow(rowNum);
        }
        return null;
    }


    /**
     * 创建工作表的实用方法，如果工作表已存在则返回现有工作表，否则创建新的工作表。
     *
     * @param workbook  包含工作表的工作簿。
     * @param sheetName 要创建或获取的工作表的名称。
     * @return          要创建或获取的工作表，如果工作表已存在则返回现有工作表，否则返回新创建的工作表。
     */
    public static Sheet createSheet(Workbook workbook, String sheetName) {
        Sheet sheet = workbook.getSheet(sheetName);
        if (sheet != null) {
            return sheet;
        }
        return workbook.createSheet(sheetName);
    }

    /**
     * 创建行的实用方法，如果行已存在则返回现有行，否则创建新的行。
     *
     * @param sheet   包含行的工作表。
     * @param rowNum  要创建或获取的行的行号。
     * @return        要创建或获取的行，如果行已存在则返回现有行，否则返回新创建的行。
     */
    public static Row createRow(Sheet sheet, int rowNum) {
        Row row = sheet.getRow(rowNum);
        if (row == null) {
            row = sheet.createRow(rowNum);
        }
        setRowHeight(row);
        return row;
    }

    /**
     * 在给定工作表中创建新行的实用方法。新行的行号将是最后一行的行号加一。
     *
     * @param sheet  包含行的工作表。
     * @return       新创建的行。
     */
    public static Row createRow(Sheet sheet){
        int lastRowIndex = getLastRowIndex(sheet);
        return createRow(sheet,lastRowIndex);
    }

    /**
     * 创建单元格的实用方法，如果单元格已存在则返回现有单元格，否则创建新的单元格。
     *
     * @param row      包含单元格的行。
     * @param cellNum  要创建或获取的单元格的列号。
     * @return         要创建或获取的单元格，如果单元格已存在则返回现有单元格，否则返回新创建的单元格。
     */
    public static Cell createCell(Row row,int cellNum){
        Cell cell = row.getCell(cellNum);
        if (cell==null){
            cell  = row.createCell(cellNum);
        }
        return cell;
    }

    /**
     * 在给定行中创建新单元格的实用方法。新单元格的列号将是最后一列的列号加一。
     *
     * @param row  包含单元格的行。
     * @return     新创建的单元格。
     */
    public static Cell createCell(Row row){
        short lastCellIndex = getLastCellIndex(row);
        return createCell(row,lastCellIndex);
    }

    /**
     * 设置单元格样式的实用方法。
     *
     * @param cell       要设置样式的单元格。
     * @param cellStyle  要应用于单元格的样式。
     */
    public static void setCellStyle(Cell cell,CellStyle cellStyle){
        if (cell !=null && cellStyle!=null){
            cell.setCellStyle(cellStyle);
        }
    }

    /**
     * 设置单元格的公式的实用方法。
     *
     * @param cell     要设置公式的单元格。
     * @param formula  要设置的公式字符串。
     */
    public static void setFormula(Cell cell,String formula){
        if (cell !=null && formula!=null && formula.length()>0){
            cell.setCellFormula(formula);
        }
    }

    /**
     * 设置行高的实用方法。
     *
     * @param row  要设置高度的行。
     */
    public static Row setRowHeight(Row row){
        return setRowHeight(row,(short) (25 * 20));
    }

    /**
     * 设置行高的实用方法。
     *
     * @param row     要设置高度的行。
     * @param height  要设置的行高度。
     * @return        设置高度后的行。
     */
    public static Row setRowHeight(Row row,Short height){
        if (row!=null && height!=null) {
            row.setHeight(height);
        }
        return row;
    }

    /**
     * 设置单元格宽度的实用方法。
     *
     * @param sheet    要设置列宽的工作表。
     * @param cellNum  要设置宽度的单元格列号。
     * @param width    要设置的单元格宽度。
     */
    public static void setCellWidth(Sheet sheet,int cellNum,Integer width){
        if (sheet!=null && width!=null){
            sheet.setColumnWidth(cellNum,width*256);
        }
    }

    /**
     * 创建单元格的实用方法，同时设置单元格的值和样式。
     *
     * @param row        包含单元格的行。
     * @param cellNum    要创建或获取的单元格的列号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @return           创建或获取的单元格。
     */
    public static Cell createCell(Row row, int cellNum, Object value, CellStyle cellStyle){
        Cell cell = createCell(row,cellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
        return cell;
    }

    /**
     * 创建单元格的实用方法，同时设置单元格的值、样式和公式。
     *
     * @param row        包含单元格的行。
     * @param cellNum    要创建或获取的单元格的列号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param formula    要设置的公式字符串。
     * @return           创建或获取的单元格。
     */
    public static Cell createCell(Row row, int cellNum, Object value, CellStyle cellStyle,String formula){
        Cell cell = createCell(row, cellNum, value, cellStyle);
        setFormula(cell,formula);
        return cell;
    }

    /**
     * 在给定行中创建新单元格的实用方法，同时设置单元格的值和样式。
     * 新单元格的列号将是最后一列的列号加一。
     *
     * @param row        包含单元格的行。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @return           创建的单元格。
     */
    public static Cell createCell(Row row, Object value, CellStyle cellStyle) {
        short lastCellNum = getLastCellIndex(row);
        return createCell(row, lastCellNum, value, cellStyle);
    }

    /**
     * 在给定行中创建新单元格的实用方法，同时设置单元格的值、样式和公式。
     * 新单元格的列号将是最后一列的列号加一。
     *
     * @param row        包含单元格的行。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param formula    要设置的公式字符串。
     * @return           创建的单元格。
     */
    public static Cell createCell(Row row, Object value, CellStyle cellStyle,String formula){
        short lastCellNum = getLastCellIndex(row);
        Cell cell = createCell(row, lastCellNum, value, cellStyle);
        setFormula(cell,formula);
        return cell;
    }


    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值和样式。
     *
     * @param sheet      要创建单元格的工作表。
     * @param rowNum     要创建单元格的行号。
     * @param cellNum    要创建单元格的列号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     */
    public static void createCell(Sheet sheet, int rowNum, int cellNum,Object value,CellStyle cellStyle){
        Row row = createRow(sheet, rowNum);
        Cell cell = createCell(row, cellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值和样式。
     * 新单元格的列号将是最后一列的列号加一。
     *
     * @param sheet      要创建单元格的工作表。
     * @param rowNum     要创建单元格的行号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     */
    public static void createCell(Sheet sheet, int rowNum, Object value,CellStyle cellStyle){
        Row row = createRow(sheet, rowNum);
        short lastCellNum = getLastCellIndex(row);
        Cell cell = createCell(row, lastCellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值、样式和列宽度。
     * 新单元格的行号将是最后一行的行号加一，新单元格的列号将是最后一列的列号加一。
     *
     * @param sheet      要创建单元格的工作表。
     * @param row        Row
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param width      要设置的单元格宽度。
     */
    public static void createCell(Sheet sheet,Row row, Object value,CellStyle cellStyle,Integer width){
        short lastCellNum = getLastCellIndex(row);
        Cell cell = createCell(row, lastCellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
        setCellWidth(sheet,lastCellNum,width);
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值和样式。
     *
     * @param sheet      要创建单元格的工作表。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     */
    public static void createCell(Sheet sheet,Row row, Object value,CellStyle cellStyle){
        createCell(sheet,row,value,cellStyle,null);
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值、样式和列宽度。
     *
     * @param sheet      要创建单元格的工作表。
     * @param rowNum     要创建单元格的行号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param width      要设置的单元格宽度。
     */
    public static void createCell(Sheet sheet, int rowNum,Object value,CellStyle cellStyle,Integer width){
        Row row = createRow(sheet, rowNum);
        short lastCellNum = getLastCellIndex(row);
        Cell cell = createCell(row, lastCellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
        setCellWidth(sheet,lastCellNum,width);
    }

    /**
     * 获取工作表的最后一行索引
     * @param sheet 工作表对象
     * @return 最后一行的索引，如果工作表为空或无行，则返回0
     */
    public static int getLastRowIndex(Sheet sheet) {
        if (sheet != null) {
            int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
            return physicalNumberOfRows;
        }
        return -1;
    }

    /**
     * 获取行的最后一个单元格的索引
     * @param row 行对象
     * @return 最后一个单元格的索引，如果行为空或无单元格，则返回0
     */
    public static short getLastCellIndex(Row row) {
        if (row != null) {
            short lastCellNum = row.getLastCellNum();
            return lastCellNum >= 0 ? lastCellNum : 0;
        }
        return -1;
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值、样式和列宽度。
     *
     * @param sheet      要创建单元格的工作表。
     * @param rowNum     要创建单元格的行号。
     * @param cellNum    要创建单元格的列号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param width      要设置的单元格宽度。
     */
    public static void createCell(Sheet sheet, int rowNum, int cellNum,Object value,CellStyle cellStyle,Integer width){
        Row row = createRow(sheet, rowNum);
        Cell cell = createCell(row, cellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
        setCellWidth(sheet,cellNum,width);
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值、样式和公式。
     *
     * @param sheet      要创建单元格的工作表。
     * @param rowNum     要创建单元格的行号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param formula    要设置的公式字符串。
     */
    public static void createCell(Sheet sheet, int rowNum, Object value,CellStyle cellStyle,String formula){
        Row row = createRow(sheet, rowNum);
        short lastCellNum = getLastCellIndex(row);
        Cell cell = createCell(row, lastCellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
        setFormula(cell,formula);
    }

    /**
     * 在给定工作表中创建新的单元格，同时设置单元格的值、样式和公式。
     *
     * @param sheet      要创建单元格的工作表。
     * @param rowNum     要创建单元格的行号。
     * @param cellNum    要创建单元格的列号。
     * @param value      要设置的单元格值。
     * @param cellStyle  要应用于单元格的样式。
     * @param formula    要设置的公式字符串。
     */
    public static void createCell(Sheet sheet, int rowNum, int cellNum,Object value,CellStyle cellStyle,String formula){
        Row row = createRow(sheet, rowNum);
        Cell cell = createCell(row, cellNum);
        setCellStyle(cell,cellStyle);
        setCellValue(cell,value);
        setFormula(cell,formula);
    }

    /**
     * 设置单元格的值。
     *
     * @param cell   要设置值的单元格
     * @param value  单元格的值
     */
    private static void setCellValue(Cell cell, Object value) {
        if (cell == null || value == null) {
            return;
        }
        if (value instanceof Double
                || value instanceof BigDecimal
                || value instanceof Float) {
            double numericValue = value instanceof Double ? (Double) value : value instanceof BigDecimal ? ((BigDecimal) value).doubleValue() :((Float) value).doubleValue();
            cell.setCellValue(numericValue);
        } else if (value instanceof String
                || value instanceof Integer
                || value instanceof Long
                || value instanceof Short
                || value instanceof Byte) {
            cell.setCellValue(value.toString());
        } else if (value instanceof Date) {
            cell.setCellValue((Date) value);
        }
    }

    /**
     * 获取单元格的值。
     *
     * @param cell  要获取值的单元格
     * @return      单元格的值
     */
    public static Object getCellValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellTypeEnum()) {
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)){
                    return cell.getDateCellValue();
                }
                return cell.getNumericCellValue();
            case STRING:
                return cell.getStringCellValue();
            case FORMULA:
                FormulaEvaluator formulaEvaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
                if (formulaEvaluator!=null){
                    CellValue evaluate = formulaEvaluator.evaluate(cell);
                    if (evaluate!=null){
                        switch (evaluate.getCellType()){
                            case STRING:
                                return evaluate.getStringValue();
                            case NUMERIC:
                                if (DateUtil.isCellDateFormatted(cell)){
                                    return cell.getDateCellValue();
                                }
                                return evaluate.getNumberValue();
                            default:
                                return null;
                        }
                    }
                }
                return null;
            default:
                return null;
        }
    }



    /**
     * 设置单元格样式的数据格式
     *
     * @param workbook  工作簿对象
     * @param cellStyle 单元格样式
     * @param format    数据格式
     */
    public static void setCellStyleDataFormat(Workbook workbook, CellStyle cellStyle, String format) {
        if (workbook != null && cellStyle != null && format!=null && format.length()>0) {
            short dataFormat = workbook.getCreationHelper().createDataFormat().getFormat(format);
            cellStyle.setDataFormat(dataFormat);
        }
    }

    /**
     * 在工作表中添加合并区域的实用方法。
     *
     * @param sheet      要添加合并区域的工作表。
     * @param firstRow   合并区域的第一行号。
     * @param lastRow    合并区域的最后一行号。
     * @param firstCol   合并区域的第一列号。
     * @param lastCol    合并区域的最后一列号。
     */
    public static void addMergedRegion(Sheet sheet,int firstRow, int lastRow, int firstCol, int lastCol){
        if (sheet!=null){
            sheet.addMergedRegion(new CellRangeAddress(firstRow,lastRow,firstCol,lastCol));
        }
    }


    public static SXSSFWorkbook createSXSSFWorkbook(){
        return new SXSSFWorkbook();
    }


    /**
     * 创建标题样式
     *
     * @param wb 工作簿对象
     * @return 标题样式
     */
    public static CellStyle createTitleCellStyle(Workbook wb) {
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setWrapText(true); // 设置自动换行

        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 背景颜色

        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中

        cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); // 左边框
        cellStyle.setBorderRight(BorderStyle.THIN); // 右边框
        cellStyle.setBorderTop(BorderStyle.THIN); // 上边框

        Font titleFont = wb.createFont(); // 创建字体样式
        titleFont.setBold(true); // 字体加粗
        titleFont.setFontName("黑体"); // 设置字体类型
        titleFont.setFontHeightInPoints((short) 12); // 设置字体大小
        cellStyle.setFont(titleFont); // 设置字体样式
        return cellStyle;
    }




    /**
     * 创建表头样式
     *
     * @param wb 工作簿对象
     * @return 表头样式
     */
    public static CellStyle createHeadCellStyle(Workbook wb) {
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setWrapText(true); // 设置自动换行
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 背景颜色
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充模式

        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中

        cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); // 左边框
        cellStyle.setBorderRight(BorderStyle.THIN); // 右边框
        cellStyle.setBorderTop(BorderStyle.THIN); // 上边框

        Font headerFont = wb.createFont(); // 创建字体样式
        headerFont.setBold(true); // 字体加粗
        headerFont.setFontName("黑体"); // 设置字体类型
        headerFont.setFontHeightInPoints((short) 15); // 设置字体大小
        cellStyle.setFont(headerFont); // 设置字体样式

        return cellStyle;
    }


    /**
     * 创建内容样式
     *
     * @param wb 工作簿对象
     * @return 单元格样式
     */
    public static CellStyle createContentCellStyle(Workbook wb) {
        // 生成字体
        Font font = wb.createFont();
        font.setColor(IndexedColors.BLACK.getIndex()); // 字体颜色
        font.setFontHeightInPoints((short) 10.5); // 字体大小

        // 生成样式
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
        cellStyle.setWrapText(true); // 设置自动换行
        cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); // 左边框
        cellStyle.setBorderRight(BorderStyle.THIN); // 右边框
        cellStyle.setBorderTop(BorderStyle.THIN); // 上边框
        cellStyle.setFont(font); // 设置字体

        return cellStyle;
    }


    /**
     * 设置工作表指定列的列宽度
     *
     * @param sheet   工作表对象
     * @param cellNum 列号
     */
    public static void setColumnWidth(Sheet sheet, int cellNum) {
        // 自动调整列宽
        sheet.autoSizeColumn(cellNum);

        // 设置列宽度，限制最小值为15个字符宽度，最大值为255个字符宽度
        int originalWidth = sheet.getColumnWidth(cellNum);
        int maxWidth = 255 * 256;
        int minWidth = 15 * 256;
        int newWidth = Math.max(minWidth, Math.min(maxWidth, originalWidth * 11 / 10));
        sheet.setColumnWidth(cellNum, newWidth);
    }

    /**
     * 设置 SXSSFWorkbook 单元格列宽度
     *
     * @param sheet   工作表对象
     * @param cellNum 列号
     */
    public static void setSXSSFWorkbookColumnWidth(Sheet sheet, int cellNum) {
        int originalWidth = sheet.getColumnWidth(cellNum);
        int maxWidth = 255 * 256;
        int minWidth = 15 * 256;
        int newWidth = Math.max(minWidth, Math.min(maxWidth, originalWidth * 11 / 10));
        sheet.setColumnWidth(cellNum, newWidth);
    }

    /**
     * 设置单元格宽度。
     *
     * @param sheet       要设置宽度的工作表
     * @param columnIndex 要设置宽度的列索引
     * @param width       宽度值
     */
    public static void setColumnWidth(Sheet sheet, int columnIndex, int width) {
        if (sheet == null || columnIndex < 0 || width < 0) {
            return;
        }
        // 考虑超出 Excel 宽度限制的情况
        if (width > 255) {
            width = 255;
        }
        // 考虑列不存在的情况
        if (sheet.getColumnWidth(columnIndex) != width) {
            sheet.setColumnWidth(columnIndex, width);
        }
    }


    /**
     * 设置工作表中指定行和列的列宽。
     * 如果工作表不是 SXSSFSheet 类型，将自动调整列宽。
     *
     * @param sheet    要设置列宽的工作表。
     * @param rowNum   要获取行的行号。
     * @param cellNum  要获取单元格的列号。
     */
    public static void setColumnWith(Sheet sheet, int rowNum, int cellNum) {
        if (!(sheet instanceof SXSSFSheet)) {
            sheet.autoSizeColumn(cellNum);
        }
        Row row = sheet.getRow(rowNum);
        if (row != null) {
            Cell cell = row.getCell(cellNum);
            if (cell != null) {
                int columnWidth = sheet.getColumnWidth(cellNum) / 256;
                int length = cell.getStringCellValue().getBytes().length;
                // 将列宽设置为字符串长度的两倍
                int newColumnWidth =  (int) (length * 1.3);
                if (columnWidth < newColumnWidth) {
                    columnWidth = newColumnWidth;
                }
                sheet.setColumnWidth(cellNum, columnWidth * 256);
            }
        }
    }


    /**
     * 根据输入流转换为 Workbook 对象（适用于直接从流中读取 Excel 文件）
     *
     * @param inputStream 输入流
     * @return Workbook 对象，如果转换失败则返回 null
     */
    public static Workbook inputStreamToXSSFWorkbook(InputStream inputStream) {
        Workbook wb = null;
        try {
            wb = new XSSFWorkbook(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wb;
    }

    /**
     * 根据输入流转换为 Workbook 对象（适用于直接从流中读取 Excel 文件）
     *
     * @param inputStream 输入流
     * @return Workbook 对象，如果转换失败则返回 null
     */
    public static Workbook inputStreamToHSSFWorkbook(InputStream inputStream) {
        Workbook wb = null;
        try {
            wb = new HSSFWorkbook(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wb;
    }



}

